package com.livepan.main.controller;

import com.alibaba.fastjson.JSONObject;
import com.livepan.main.controller.viewobject.SubmissionVO;
import com.livepan.server.BaseController;
import com.livepan.server.error.BusinessException;
import com.livepan.server.response.CommonReturnType;
import com.livepan.server.service.ContestService;
import com.livepan.server.service.ProblemService;
import com.livepan.server.service.SubmissionService;
import com.livepan.server.service.model.ProblemModel;
import com.livepan.server.service.model.SubmissionModel;
import com.livepan.server.service.model.UserModel;
import com.livepan.server.utils.CalendarUtil;
import com.livepan.server.utils.ConstUtil;
import com.livepan.server.utils.PushJudgerUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController("submission")
@RequestMapping(value = "/submission")
public class SubmissionController extends BaseController {

    @Autowired
    private SubmissionService submissionService;

    @Autowired
    private ProblemService problemService;

    @Autowired
    private ContestService contestService;

    @RequestMapping("/getById")
    @ResponseBody
    public CommonReturnType getSubmissionById(@RequestParam("runId") Integer runId) throws BusinessException {
        SubmissionModel submissionModel = submissionService.getSubmissionById(runId);
        UserModel userModel = getUserModelFromSession();
        if (!userModel.getId().equals(submissionModel.getUserId())) {
            submissionModel.setSourcecode(null);
        }
        SubmissionVO submissionVO = convertSubmissionVOFromSubmissionModel(submissionModel);
        return CommonReturnType.create(submissionVO);
    }

    @RequestMapping("/getList")
    @ResponseBody
    public CommonReturnType getSubmissionList(@RequestParam(value = "userId", required = false) String userId,
                                              @RequestParam(value = "problemId", required = false) Integer problemId,
                                              @RequestParam(value = "page", defaultValue = "1") Integer page,
                                              @RequestParam(value = "language", required = false) Short language,
                                              @RequestParam(value = "status", required = false) Integer status,
                                              @RequestParam(value = "contestId", defaultValue = "-1") Integer contestId) {
        int count = submissionService.querySubmissionCount(userId, problemId, language, contestId, status);

        int offset = (page - 1) * ConstUtil.submissionLimit;
        int limit = ConstUtil.submissionLimit;


        List<SubmissionModel> submissionModelList = submissionService
                .querySubmissionList(userId, problemId, language, contestId, status, offset, limit);

        List<SubmissionVO> submissionVOList = submissionModelList
                .stream().map(this::convertSubmissionVOFromSubmissionModel).collect(Collectors.toList());

        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("totalCount", count);
        resultMap.put("submissionList", submissionVOList);

        return CommonReturnType.create(resultMap);
    }

    @RequestMapping("/upload")
    @ResponseBody
    public CommonReturnType uploadSubmission(@RequestBody SubmissionModel submissionModel) throws BusinessException, IOException {
        UserModel userModel = getUserModelFromSession();

        if (submissionModel.getContestId() == null) {
            submissionModel.setContestId(-1);
        }

        //如果是比赛的题目，那么就检查权限和时间
        if (submissionModel.getContestId() != -1) {
            contestService.checkContestSubmitPermission(submissionModel.getContestId(), userModel.getId());
        }

        Calendar calendar = Calendar.getInstance();
        submissionModel.setSubmitTime(CalendarUtil.calendarToString(calendar));
        submissionModel.setLength(submissionModel.getSourcecode().length());
        submissionModel.setUserId(userModel.getId());

        problemService.addSubmitCount(submissionModel.getProblemId(), -1, 1);

        SubmissionModel createdSubmissionModel = submissionService.createSubmission(submissionModel);

        //todo 比赛的提交需要统一进行提交判题端判题
        //不是比赛的题目，那就直接push
        if (createdSubmissionModel.getContestId() == null || createdSubmissionModel.getContestId() == -1) {
            ProblemModel problemModel = problemService.getProblemByID(submissionModel.getProblemId());

            createdSubmissionModel.setContestId(-1);

            PushJudgerUtil.getInstance().pushJudge(createdSubmissionModel, problemModel);
        }

        return CommonReturnType.create(createdSubmissionModel);

    }

    @RequestMapping("/update")
    @ResponseBody
    public CommonReturnType updateSubmission(@RequestBody JSONObject judgeData
    ) throws BusinessException {
        Integer runId = judgeData.getInteger("runId");
        Integer result = judgeData.getInteger("result");
        Integer memoryUsed = judgeData.getInteger("memoryUsed");
        Integer timeUsed = judgeData.getInteger("timeUsed");
        String ext = judgeData.getString("ext");
        Integer score = judgeData.getInteger("score");
        SubmissionModel submissionModel = submissionService.getSubmissionById(runId);
        submissionModel.setResult(result.byteValue());
        if (memoryUsed != null) {
            submissionModel.setMemoryused(memoryUsed);
        }
        if (timeUsed != null) {
            submissionModel.setTimeused(timeUsed);
        }
        if (ext != null) {
            submissionModel.setExt(ext);
        }

        if (score != null) {
            submissionModel.setScore(score);
        }

        if (score != null && !submissionService.getSubmissionById(runId).getScore().equals(score)) {
            if (score == 100) {
                //满分就Ac的数量加一
                problemService.addAcceptedCount(submissionModel.getProblemId(), submissionModel.getContestId(), 1);
            }
            //原先是满分，现在不是了
            else if (submissionService.getSubmissionById(runId).getScore() == 100) {
                problemService.addAcceptedCount(submissionModel.getProblemId(), submissionModel.getContestId(), -1);

            }
        }
        submissionService.updateSubmission(submissionModel);


        return CommonReturnType.create(submissionModel);
    }

    @RequestMapping("/rejudge")
    @ResponseBody
    public CommonReturnType reJudgeProblem(
            @RequestParam(value = "problemId", required = false) Integer problemId,
            @RequestParam(value = "contestId", required = false) Integer contestId,
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "submissionId", required = false) Integer submissionId) throws IOException {
        if (submissionId != null) {
            submissionService.reJudge(submissionId);
        } else {
            submissionService.reJudge(contestId, userId, problemId);
        }
        return CommonReturnType.create(null);
    }

    private SubmissionVO convertSubmissionVOFromSubmissionModel(SubmissionModel submissionModel) {
        if (submissionModel == null) {
            return null;
        }
        SubmissionVO submissionVO = new SubmissionVO();

        BeanUtils.copyProperties(submissionModel, submissionVO);

        return submissionVO;
    }

}
